function createElement(tagName, innerHTML, attributes) {
	var element = document.createElement(tagName);
	if (innerHTML && innerHTML != undefined)
		element.innerHTML = innerHTML;
	for (var i in attributes) {
		element.setAttribute(i, attributes[i]);
	}
	return element;
}

function listToHTML(list, elementId, linkView, method, idId, isLink) {
	if (isLink == undefined)
		isLink = true;
	var htmlList = createElement('ul', null);
	for ( var i = 0; i < list.length; i++) {
		var innerHTML = elementId ? list[i][elementId] : list[i];
		var element = createElement('li', null);
		var href = 'javascript:loadContent(\'' + linkView + '\', \'' + method + '\', \'' + list[i][idId] + '\');';
		if (isLink)
			element.appendChild(createElement('a', innerHTML, {href : href}));
		else {
			var a = createElement('a', innerHTML);
			a.potHref = href;
			element.appendChild(a);
		}
		htmlList.appendChild(element);
	}
	return htmlList;
}

function getMultipeSelectValues(select) {
	var arSelected = new Array();
	while (select.selectedIndex != -1) {
		arSelected.push(parseInt(select.options[select.selectedIndex].value));
		select.options[select.selectedIndex].selected = false;
	}
	var result = new Object();
	result.id = arSelected;

	return result;
}

function createForm(elements) {
	var form = createElement('form');
	var table = createElement('table');
	form.appendChild(table);
	for (elementId in elements) {
		if (!elements[elementId].type)
			continue;
		if (!elements[elementId].label)
			elements[elementId].label = 'Undefined';
		
		var tr = createElement('tr');
		if (elements[elementId].type != 'button')
			tr.appendChild(createElement('td', elements[elementId].label + ': '));
		var td = createElement('td');
		tr.appendChild(td);
		switch (elements[elementId].type) {
			case 'text': case 'password' :
				var element = createElement('input', null, { id : elementId, name : elementId, type : elements[elementId].type} );
				if (elements[elementId].value)
					element.value = elements[elementId].value;
				td.appendChild(element);
				break;
			case 'textarea' :
				td.appendChild(createElement('textarea', null, { id : elementId, name : elementId }));
				break;
			case 'select' :
				var select = createElement('select', '', { id : elementId, name : elementId, multiple : 'multiple'});
				select.refreshSelected = function() {
					for (var i in this.selected) {
						if (this.selected[i].id)
							this.getElementById(this.selected[i].id).selected = true;
						else {
							var elements = this.getElementsByTagName('option');
							for (var e in elements) {
								if (elements[e].innerHTML == this.selected[i])
									elements[e].selected = true;
							}
						}
					}
				}
				td.appendChild(select);
				var fill = elements[elementId].fillFunction;
				fill[0](select, fill[1]);
				break;
			case 'button' :
				var a = elements[elementId].action;
				var button = createElement('input', null, { id : elementId, type : 'button', value : elements[elementId].value });
				if (a[0] == loadContent)
					button.onclick = function(e) { a[0](a[1], a[2], a[3], form.serialize(true)); };
				else
					button.onclick = function(e) { a[0](form, a[1]); };
				td.setAttribute('colspan', 2);
				td.appendChild(button);
				break;
			default:
				break;;
		}
		table.appendChild(tr);
	}
	return form;
}

function fillSelectAsync(select, path) {
	window.selectTmpFinal = select;
	
	var options = {
		method : 'get',
		requestHeaders : {
			Accept : 'application/json',
			'Content-Type' : 'application/json; charset=UTF-8'
		},
		onSuccess : function(transport) {
			json = transport.responseJSON;
			for (var i=0; i<json.length; i++)
				select.appendChild(createElement('option', json[i].name, {value:json[i].id}));

			select.refreshSelected();
		}
	};
	
	new Ajax.Request('/json/' + path + '/', options);
	
}

function modifySerialized(form, path) {
	submitSerialized(form, path, 'put');
}

function submitSerialized(form, path, method, method2) {
	json = Object.toJSON(form.serialize(true));
	if (!method)
		method = 'post';
	method = method.toUpperCase();
	if (!method2)
		method2 = 'get';
	
	var requestHeaders = {
			Accept : 'application/json',
			'Content-Type' : 'application/json; charset=UTF-8',
		};
	if (method != 'GET' && method != 'POST') {
		requestHeaders["X-HTTP-Method-Override"] = method;
		method = 'POST';
	} 
	
	var options = {
		method : method,
		postBody : json,
		requestHeaders : requestHeaders,
		onSuccess : function(transport) {
			var tmp = path.indexOf('/');
			if (tmp < 0)
				loadContent(path, method2);
			else
				loadContent(path.substring(0, tmp), method2);
		},
		onFailiure : function() {
			window.viewContainer.removeChild(window.tmpFormFinal);
			window.viewContainer.appendChild(createElement('p', 'New recipie could not be added!', { style : 'color:#00ffff;' }));
		},
		on405 : function() {
			window.tmpFormFinal.parentNode.removeChild(window.tmpFormFinal);
			window.viewContainer.appendChild(createElement('p', 'Method not allowed', { style : 'color:#ff0000;' }));
		},
		on500 : function() {
			window.tmpFormFinal.parentNode.removeChild(window.tmpFormFinal);
			window.viewContainer.appendChild(createElement('p', 'Web service internal error...', { style : 'color:#ff0000;' }));
		}
	};
	
	new Ajax.Request('/json/' + path + '/', options);
}

function fillForm(form, path, id) {
	window.formTmpFinal = form;
	
	var options = {
		method : 'get',
		requestHeaders : {
			Accept : 'application/json',
			'Content-Type' : 'application/json; charset=UTF-8'
		},
		onSuccess : function(transport) {
			json = transport.responseJSON;
			window.formTmpFinal.elements['name'].value = json['name'];
			window.formTmpFinal.elements['description'].value = json['description'];
			window.formTmpFinal.elements['categories'].selected = json['categories'];
			window.formTmpFinal.elements['items'].selected = json['items'];
			window.formTmpFinal.elements['categories'].refreshSelected();
			window.formTmpFinal.elements['items'].refreshSelected();
		}
	};
	
	new Ajax.Request('/json/' + path + '/' + id + '/', options);
}

function modifyContent(view, name, id, ignorable2) {

	if (window.tmpFormFinal && window.tmpFormFinal.parentNode == window.viewContainer)
		window.viewContainer.removeChild(window.tmpFormFinal);
	var form;
	switch(view) {
		case 'recipie' :
			form = createForm({
				'name' : { type : 'text', label : 'Name' },
				'categories' : { type : 'select', label : 'Categories', fillFunction : [fillSelectAsync, 'category'] },
				'items' : { type : 'select', label : 'Items', fillFunction : [fillSelectAsync, 'item'] },
				'description' : { type : 'textarea', label : 'Description' },
				'submit' : { type : 'button', value : 'Modify recipie', action : [modifySerialized, 'recipie/' + id] }
			});
			fillForm(form, view, id);
			break;
		case 'item' :
			form = createForm({
				'name' : { type : 'text', label : 'Name', value : name },
				'submit' : { type : 'button', value : 'Modify item', action : [modifySerialized, 'item/' + id] }
			});
			break;
		case 'category' :
			form = createForm({
				'name' : { type : 'text', label : 'Name', value : name },
				'submit' : { type : 'button', value : 'Modify category', action : [modifySerialized, 'category/' + id] }
			});
			break;
		default:
			return;
	}
	window.viewContainer.appendChild(form);
	window.tmpFormFinal = form;
}

function loadContent(view, method, id, postObj) {
	
	window.viewContainer = $('content');
	window.viewContainer.innerHTML = '';
	if (!method) {
		if (!views[view])
			window.viewContainer.innerHTML = 'No handlers defined for view ' + view + '.';
		else
			views[view](window.viewContainer);
		return;
	}
	window.view = view;
	
	var path = '/json/' + view + '/';
	if (id) {
		path += id + '/';
		window.view += 'X';
	}
	
	var requestHeaders = {
		Accept : 'application/json',
		'Content-Type' : 'application/json; charset=UTF-8',
	};
	if (method)
		method = method.toUpperCase();
	else
		method = 'POST';
	
	if (method != 'GET' && method != 'POST') {
		requestHeaders["X-HTTP-Method-Override"] = method;
		method = 'POST';
	}

	var options = {
		method : method,
		requestHeaders : requestHeaders,
		onSuccess : function(transport) {
			if (!views[method])
				window.viewContainer.innerHTML = 'No handlers defined for method ' + method + '.';
			else if (!views[method][window.view])
				window.viewContainer.innerHTML = 'No handler defined for view '
					+ view + ', method ' + method + '.';
			else
				views[method][window.view](transport.responseJSON, window.viewContainer);
		},
		onFailure : function(transport) {
			if (transport.status == 409)
				window.viewContainer.innerHTML = 'Username already exists!';
			else
				window.viewContainer.innerHTML = 'Application failed to process your request!';
		},
		on500 : function(transport) {
			window.tmpContainerFinal.appendChild(createElement('p', 'Web service internal error', { style : 'color:#ff0000;' }));
		}
	};

	if (postObj)
		options.postBody = Object.toJSON(postObj);
	new Ajax.Request(path, options);
}

var views = {
	home : function(container) {
		container.appendChild(createElement('h2', 'Welcome to MacGyver web client!'));
	},
	about : function(container) {
		container.appendChild(createElement('h2', 'Who are we?'));
		container.appendChild(createElement('p', 'We are MacGyver. We built this service to help the rest of the world, and to help ourselves.'));
		container.appendChild(createElement('h2', 'Why MacGyver Cookbook?'));
		container.appendChild(createElement('p', 'Because we can. Yes, we can.'));
	},
	searchRecipies : function(container) {
		container.appendChild(createElement('h2', 'Search recipies trough items used'));
		container.appendChild(createElement('label', 'Items: ', { 'for' : 'id_items' }));
		var select = createElement('select', '', { id : 'id_items', name : 'items', multiple : 'multiple'});
		fillSelectAsync(select, 'item');
		container.appendChild(select);
		container.appendChild(createElement('input', '', { type : 'submit', value : 'Search', onclick : 'loadContent(\'recipieSearch\', \'post\', null, getMultipeSelectValues($(\'id_items\')));'}));
	},
	register : function(container) {
	container.appendChild(createElement('h2', 'Register new user:'));
		var form = createForm({
			'username' : { type : 'text', label : 'Username' },
			'password' : { type : 'password', label : 'Password' },
			'submit' : { type : 'button', value : 'Register', action : [loadContent, 'registerUser', 'post', null] }
		});
		container.appendChild(form);
	},
	GET : {
		recipie : function(json, container) {
			container.innerHTML = 'Found ' + (json ? json.length : 0) + ' recipies:';
			window.tmpContainerFinal = container;
			var button = createElement('button', 'Add new');
			var button2 = createElement('button', 'Remove existing');
			var button3 = createElement('button', 'Modify existing');
			button2.altLabel = 'Select recipies to delete';;
			button3.altLabel = 'Select recipies to modify';
			window.tmpButtonFinal = button;
			window.tmpButtonFinal2 = button2;
			window.tmpButtonFinal3 = button3;
			if (button2.clicked == undefined)
				button2.clicked = false;
			if (button3.clicked == undefined)
				button3.clicked = false;
			if (json) {
				var list = listToHTML(json, 'name', 'recipie', 'get', 'id');
				window.tmpListFinal = list;
				container.appendChild(list);
				container.appendChild(button2);
				container.appendChild(button3);
			}
			container.appendChild(button);
			button.onclick = function() {
				if (window.tmpFormFinal && window.tmpFormFinal.parentNode == window.tmpContainerFinal)
					window.tmpContainerFinal.removeChild(window.tmpFormFinal);
				var form = createForm({
					'name' : { type : 'text', label : 'Name' },
					'categories' : { type : 'select', label : 'Categories', fillFunction : [fillSelectAsync, 'category'] },
					'items' : { type : 'select', label : 'Items', fillFunction : [fillSelectAsync, 'item'] },
					'description' : { type : 'textarea', label : 'Description' },
					'submit' : { type : 'button', value : 'Submit recipie', action : [submitSerialized, 'recipie'] }
				});
				window.tmpContainerFinal.appendChild(form);
				window.tmpFormFinal = form;
			};
			button2.onclick = function() {
				if (!window.tmpButtonFinal2.isClicked && window.tmpButtonFinal3.isClicked)
					window.tmpButtonFinal3.onclick();
				var isClicked = window.tmpButtonFinal2.isClicked = !window.tmpButtonFinal2.isClicked;
				var tmpValue = window.tmpButtonFinal2.innerHTML;
				window.tmpButtonFinal2.innerHTML = window.tmpButtonFinal2.altLabel;
				window.tmpButtonFinal2.altLabel = tmpValue;
				
				var links = window.tmpListFinal.getElementsByTagName('a');
				if (isClicked) {
					for (i in links) {
						if (!links[i].getAttribute)
							continue;
						var href = links[i].getAttribute('href');
						links[i].oldHref = href;
						var index = href.indexOf('\'') + 1;
						index +=  href.substring(index).indexOf('\'') + 1;
						var indexStart = index +=  href.substring(index).indexOf('\'') + 1;
						var indexEnd = index +=  href.substring(index).indexOf('\'');
						links[i].setAttribute('href', href.substring(0, indexStart) + 'delete' + href.substring(indexEnd));
					}
				} else {
					for (i in links)
						if (links[i].setAttribute)
							links[i].setAttribute('href', links[i].oldHref);
				}
			};
			button3.onclick = function() {
				if (!window.tmpButtonFinal3.isClicked && window.tmpButtonFinal2.isClicked)
					window.tmpButtonFinal2.onclick();
				var isClicked = window.tmpButtonFinal3.isClicked = !window.tmpButtonFinal3.isClicked;
				var tmpValue = window.tmpButtonFinal3.innerHTML;
				window.tmpButtonFinal3.innerHTML = window.tmpButtonFinal3.altLabel;
				window.tmpButtonFinal3.altLabel = tmpValue;
				
				var links = window.tmpListFinal.getElementsByTagName('a');
				if (isClicked) {
					for (i in links) {
						if (!links[i].getAttribute)
							continue;
						var href = links[i].getAttribute('href');
						links[i].oldHref = href;
						var indexStart = href.indexOf(':') + 1;
						var indexEnd =  href.indexOf('(');
						links[i].setAttribute('href', href.substring(0, indexStart) + 'modifyContent' + href.substring(indexEnd));
					}
				} else {
					for (i in links)
						if (links[i].setAttribute)
							links[i].setAttribute('href', links[i].oldHref);
				}
			};
		},
		item : function(json, container) {
			container.innerHTML = 'Found ' + (json ? json.length : 0) + ' items:';
			var button = createElement('button', 'Add new');
			var button2 = createElement('button', 'Remove existing');
			var button3 = createElement('button', 'Modify existing');
			button2.altLabel = 'Select items to delete';;
			button3.altLabel = 'Select items to modify';
			window.tmpButtonFinal = button;
			window.tmpButtonFinal2 = button2;
			window.tmpButtonFinal3 = button3;
			if (button2.clicked == undefined)
				button2.clicked = false;
			if (button3.clicked == undefined)
				button3.clicked = false;
			if (json) {
				var list = listToHTML(json, 'name', 'item', 'delete', 'id', false);
				container.appendChild(list);
				window.tmpListFinal = list;
				container.appendChild(button2);
				container.appendChild(button3);
			}
			container.appendChild(button);
			
			

			button.onclick = function() {
				if (window.tmpFormFinal && window.tmpFormFinal.parentNode == window.viewContainer)
					window.viewContainer.removeChild(window.tmpFormFinal);
				var form = createForm({
					'name' : { type : 'text', label : 'Name' },
					'submit' : { type : 'button', value : 'Submit item', action : [submitSerialized, 'item'] }
				});
				window.viewContainer.appendChild(form);
				window.tmpFormFinal = form;
			};
			button2.onclick = function() {
				if (!window.tmpButtonFinal2.isClicked && window.tmpButtonFinal3.isClicked)
					window.tmpButtonFinal3.onclick();
				var isClicked = window.tmpButtonFinal2.isClicked = !window.tmpButtonFinal2.isClicked;
				var tmpValue = window.tmpButtonFinal2.innerHTML;
				window.tmpButtonFinal2.innerHTML = window.tmpButtonFinal2.altLabel;
				window.tmpButtonFinal2.altLabel = tmpValue;
				
				var links = window.tmpListFinal.getElementsByTagName('a');
				if (isClicked) {
					for (i in links) {
						if (!links[i].innerHTML)
							continue;
						var href = links[i].potHref
						var index = href.indexOf('\'') + 1;
						index +=  href.substring(index).indexOf('\'') + 1;
						var indexStart = index +=  href.substring(index).indexOf('\'') + 1;
						var indexEnd = index +=  href.substring(index).indexOf('\'');
						links[i].setAttribute('href', href.substring(0, indexStart) + 'delete' + href.substring(indexEnd));
					}
				} else {
					for (i in links)
						if (links[i].setAttribute)
							links[i].removeAttribute('href');
				}
			};
			button3.onclick = function() {
				if (!window.tmpButtonFinal3.isClicked && window.tmpButtonFinal2.isClicked)
					window.tmpButtonFinal2.onclick();
				var isClicked = window.tmpButtonFinal3.isClicked = !window.tmpButtonFinal3.isClicked;
				var tmpValue = window.tmpButtonFinal3.innerHTML;
				window.tmpButtonFinal3.innerHTML = window.tmpButtonFinal3.altLabel;
				window.tmpButtonFinal3.altLabel = tmpValue;
				
				var links = window.tmpListFinal.getElementsByTagName('a');
				if (isClicked) {
					for (i in links) {
						if (!links[i].innerHTML)
							continue;
						var href = links[i].potHref
						var indexStart = href.indexOf(':') + 1;
						var indexEnd = href.indexOf('(');
						var tmp = href.indexOf(',') + 1;
						var indexStart2 = tmp += href.substring(tmp).indexOf('\'') + 1;
						var indexEnd2 = tmp += href.substring(tmp).indexOf('\'');
						links[i].setAttribute('href', href.substring(0, indexStart) + 'modifyContent' + href.substring(indexEnd, indexStart2) + links[i].innerHTML + href.substring(indexEnd2));
					}
				} else {
					for (i in links)
						if (links[i].setAttribute)
							links[i].removeAttribute('href');
				}
			};
		},
		category : function(json, container) {
			container.innerHTML = 'Found ' + (json ? json.length : 0) + ' categories:';
			var button = createElement('button', 'Add new');
			var button2 = createElement('button', 'Remove existing');
			var button3 = createElement('button', 'Modify existing');
			button2.altLabel = 'Select categories to delete';;
			button3.altLabel = 'Select categories to modify';
			window.tmpButtonFinal = button;
			window.tmpButtonFinal2 = button2;
			window.tmpButtonFinal3 = button3;
			if (button2.clicked == undefined)
				button2.clicked = false;
			if (button3.clicked == undefined)
				button3.clicked = false;
			if (json) {
				var list = listToHTML(json, 'name', 'category', 'delete', 'id', false);
				container.appendChild(list);
				window.tmpListFinal = list;
				container.appendChild(button2);
				container.appendChild(button3);
			}
			container.appendChild(button);
			
			
			
			button.onclick = function() {
				if (window.tmpFormFinal && window.tmpFormFinal.parentNode == window.viewContainer)
					window.viewContainer.removeChild(window.tmpFormFinal);
				var form = createForm({
					'name' : { type : 'text', label : 'Name' },
					'submit' : { type : 'button', value : 'Submit category', action : [submitSerialized, 'category'] }
				});
				window.viewContainer.appendChild(form);
				window.tmpFormFinal = form;
			};
			button2.onclick = function() {
				if (!window.tmpButtonFinal2.isClicked && window.tmpButtonFinal3.isClicked)
					window.tmpButtonFinal3.onclick();
				var isClicked = window.tmpButtonFinal2.isClicked = !window.tmpButtonFinal2.isClicked;
				var tmpValue = window.tmpButtonFinal2.innerHTML;
				window.tmpButtonFinal2.innerHTML = window.tmpButtonFinal2.altLabel;
				window.tmpButtonFinal2.altLabel = tmpValue;
				
				var links = window.tmpListFinal.getElementsByTagName('a');
				if (isClicked) {
					for (i in links) {
						if (!links[i].innerHTML)
							continue;
						var href = links[i].potHref
						var index = href.indexOf('\'') + 1;
						index +=  href.substring(index).indexOf('\'') + 1;
						var indexStart = index +=  href.substring(index).indexOf('\'') + 1;
						var indexEnd = index +=  href.substring(index).indexOf('\'');
						links[i].setAttribute('href', href.substring(0, indexStart) + 'delete' + href.substring(indexEnd));
					}
				} else {
					for (i in links)
						if (links[i].setAttribute)
							links[i].removeAttribute('href');
				}
			};
			button3.onclick = function() {
				if (!window.tmpButtonFinal3.isClicked && window.tmpButtonFinal2.isClicked)
					window.tmpButtonFinal2.onclick();
				var isClicked = window.tmpButtonFinal3.isClicked = !window.tmpButtonFinal3.isClicked;
				var tmpValue = window.tmpButtonFinal3.innerHTML;
				window.tmpButtonFinal3.innerHTML = window.tmpButtonFinal3.altLabel;
				window.tmpButtonFinal3.altLabel = tmpValue;
				
				var links = window.tmpListFinal.getElementsByTagName('a');
				if (isClicked) {
					for (i in links) {
						if (!links[i].innerHTML)
							continue;
						var href = links[i].potHref
						var indexStart = href.indexOf(':') + 1;
						var indexEnd = href.indexOf('(');
						var tmp = href.indexOf(',') + 1;
						var indexStart2 = tmp += href.substring(tmp).indexOf('\'') + 1;
						var indexEnd2 = tmp += href.substring(tmp).indexOf('\'');
						links[i].setAttribute('href', href.substring(0, indexStart) + 'modifyContent' + href.substring(indexEnd, indexStart2) + links[i].innerHTML + href.substring(indexEnd2));
					}
				} else {
					for (i in links)
						if (links[i].setAttribute)
							links[i].removeAttribute('href');
				}
			};
		},
		recipieX : function(json, container) {
			container.appendChild(createElement('h2',  json.name));
			container.appendChild(createElement('p', 'Categories:'));
			container.appendChild(listToHTML(json.categories));
			container.appendChild(createElement('p', 'Items:'));
			container.appendChild(listToHTML(json.items));
			container.appendChild(createElement('p', 'Description:'));
			container.appendChild(createElement('div', json.description, {'class' : 'description'}));
		}
	},
	POST : {
		recipie : function(json, container) {
			loadContent('recipie', 'get');
		},
		item : function(json, container) {
			loadContent('item', 'get');
		},
		category : function(json, container) {
			loadContent('category', 'get');
		},
		recipieSearch : function(json, container) {
			container.appendChild(createElement('p', json ? json.length + ' recipies found for selected items.' : 'No recipies found for selected items.'));
			if (!json)
				return;
			container.appendChild(listToHTML(json, 'name', 'recipie', 'get', 'id'));
		},
		registerUser : function(json, container) {
			container.appendChild(createElement('h2', 'Registration successful!'));
		}
	},
	PUT : {
		recipieX : function(json, container) {
		loadContent('recipie', 'get');
		},
		itemX : function(json, container) {
			loadContent('item', 'get');
		},
		categoryX : function(json, container) {
			loadContent('category', 'get');
		}
	},
	DELETE : {
		recipieX : function(json, container) {
			loadContent('recipie', 'get');
		},
		itemX : function(json, container) {
			loadContent('item', 'get');
		},
		categoryX : function(json, container) {
			loadContent('category', 'get');
		}
	}
};
